package com.zunipe.chat.service;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.google.gson.Gson;
import com.zunipe.chat.ChatApplication;
import com.zunipe.chat.bean.Message;
import com.zunipe.chat.util.EncodeHelper;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ChatService extends Service {
    private Socket socket;
    public static final String CHANNEL_ID = "JuChat";
    private final Vector<ChatServiceCallback> callbackQueue = new Vector<>();
    private final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    private final Gson gson = new Gson();

    @Override
    public void onCreate() {
        super.onCreate();
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "消息", NotificationManager.IMPORTANCE_HIGH);
        notificationManager.createNotificationChannel(notificationChannel);
        ChatApplication.getInstance().setChatServiceRunning(true);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        ChatApplication.getInstance().setChatServiceRunning(false);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new ChatBinder();
    }

    public class ChatBinder extends Binder {
        public ChatBinder() {
            connectServer();
        }

        public void sendMessage(Message message) {
            fixedThreadPool.execute(() -> {
                if (!socket.isClosed()) {
                    try {
                        OutputStream outputStream = socket.getOutputStream();
                        String jsonStr = gson.toJson(message);
                        byte[] bytes = EncodeHelper.toBytes(jsonStr);
                        outputStream.write(bytes);
                        outputStream.flush();
                    } catch (IOException e) {
                        Log.e("ChatService", e.toString());
                    }
                }
            });
        }

        public void connectServer() {
            fixedThreadPool.execute(() -> {
                try {
                    socket = new Socket();
                    socket.connect(new InetSocketAddress("zunipe.com", 4560), 3000);
                    new Handler(Looper.getMainLooper()).post(() -> {
                        Toast.makeText(ChatService.this, "已连接", Toast.LENGTH_SHORT).show();
                        callbackQueue.forEach(ChatServiceCallback::onConnected);
                    });
                    InputStream is = socket.getInputStream();

                    while (!socket.isClosed()) {
                        int bodyLength = EncodeHelper.getHeader(is);
                        if (bodyLength > 0) {
                            byte[] bodyByte = new byte[bodyLength];
                            is.read(bodyByte);
                            String jsonStr = new String(bodyByte);
                            new Handler(Looper.getMainLooper()).post(() -> {
                                callbackQueue.forEach(callback -> callback.onMessageReceiver(gson.fromJson(jsonStr, Message.class)));
                            });
                        }
                    }
                } catch (IOException e) {
                    Log.e("ChatService", e.toString());
                }
            });
        }

        public void registerCallbackListener(ChatServiceCallback callback) {
            callbackQueue.add(callback);
        }

        public void unregisterCallbackListener(ChatServiceCallback callback) {
            callbackQueue.remove(callback);
        }
    }
}